#pragma once
#include"index.hpp"
#include"util.hpp"
#include<algorithm>
#include<jsoncpp/json/json.h>
#include"log.hpp"
namespace ns_searcher
{
  struct InvertedElemPrint{
    uint64_t doc_id;
    int weight;
    std::vector<std::string> words;
    InvertedElemPrint():doc_id(0),weight(0){}
  };
  class Searcher
  {
  private:
    ns_index::Index* index;
  public:
    Searcher(){}
    ~Searcher(){}
  public:
    void InitSearcher(const std::string &input)
    {
      //调用GetInstance初始化index
      index=ns_index::Index::GetInstance();
      // std::cout<<"获取index单例成功"<<std::endl;
      LOG(NORMAL,"建立index单例成功……");
      //构建索引
      index->BuildIndex(input);
      //std::cout<<"建立索引成功"<<std::endl;
      LOG(NORMAL,"建立正排索引与倒排索引成功……");
    }
    
    void Search(const std::string query,std::string *json_string)
    {
      //对关键词进行分词
      std::vector<std::string> words;
      ns_util::JiebaUtil::CutString(query,&words);
      
      //根据各个分词进行index查找
      //ns_index::InvertedList inverted_list_all;
      std::vector<InvertedElemPrint> inverted_list_all;

      std::unordered_map<uint64_t,InvertedElemPrint> tokens_map;
      
      for(std::string word:words)
      {
        boost::to_lower(word);
        ns_index::InvertedList* invered_list=index->GetInvertedList(word);//根据分词进行倒排查找，获得文档id
        if(nullptr==invered_list)
        {
          continue;
        }

        //inverted_list_all.insert(inverted_list_all.end(),invered_list->begin(),invered_list->end());//统计文档id

        for(const auto& elem:*invered_list)
        {
          auto& item=tokens_map[elem.doc_id];
          item.doc_id=elem.doc_id;
          item.weight+=elem.weight;
          item.words.push_back(elem.word);
        }
      }
      for(const auto &item:tokens_map)
      {
        inverted_list_all.push_back(std::move(item.second));
      }
      
      //对文档id进行排序
      // std::sort(inverted_list_all.begin(),inverted_list_all.end(),[](const ns_index::InvertedElem& e1,const ns_index::InvertedElem& e2){
      //     return e1.weight>e2.weight;
      //     });
      std::sort(inverted_list_all.begin(),inverted_list_all.end(),[](const InvertedElemPrint &e1,const InvertedElemPrint &e2){
        return e1.weight>e2.weight;
      });
      
      //构造json串
      Json::Value root;
      for(auto item:inverted_list_all)
      {
        //根据进行文档id，在正排索引中查找获得文档相关信息
        ns_index::DocInfo* doc=index->GetForwardIndex(item.doc_id);
        if(nullptr==doc)
        {
          continue;
        }
        Json::Value elem;
        elem["title"]=doc->title;
        elem["desc"]=GetDesc(doc->content,item.words[0]);
        elem["url"]=doc->url;
        //测试
        // elem["doc_id"]=(int)item.doc_id;
        // elem["weight"]=item.weight;
        
        root.append(elem);
      }

      Json::StyledWriter writer;
      *json_string = writer.write(root);
    }

    std::string GetDesc(const std::string& html_connect,const std::string& word)
    {
      const int prev_step=50;
      const int next_step=100;

      //size_t pos=html_connect.find(word);
      auto iter=std::search(html_connect.begin(),html_connect.end(),word.begin(),word.end(),[](int x,int y){
            return (std::tolower(x)==std::tolower(y));
          });
      if(iter==html_connect.end())
      {
        return "None1";
      }
      int pos=std::distance(html_connect.begin(),iter);
      
      
      int start=0;
      int end=html_connect.size()-1;
      
      if(pos>start+prev_step) start=pos-prev_step;
      if(pos<end-next_step) end=pos+next_step;

      if(start>=end)
      {
        return "None2";
      }
      return html_connect.substr(start,end-start);
    }
  };
}
